#include <iostream>
#include <pthread.h>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include "sock.hpp"

const std::string wwwroot = "wwwroot";
const std::string sep = "\r\n";
const std::string homeage = "index.html";


class ThreadData
{
public:
    ThreadData(int sockfd)
        : _sockfd(sockfd)
    {}

    int getsockfd()
    {
        return _sockfd;
    }

private:
    int _sockfd;
};


class HttpRequest
{
public:
    HttpRequest()
    {}
    ~HttpRequest()
    {}
    
    void DebugPrint()
    {
        for(auto ch : _hander)
        {
            std::cout << ch;
        }
        std::cout << std::endl;
        //std::cout << "text: " << _text << std::endl;
        std::cout << "------------------------------------------" << std::endl;
        std::cout << "method: " << _method << std::endl;
        std::cout << "url: " << _url  << std::endl;
        std::cout << "http_version: " << _http_version << std::endl;
        std::cout << "path: " << _path << std::endl;
        std::cout << "------------------------------------------" << std::endl;

    }

    void prase()
    {
        std::stringstream ss(_hander[0]);
        ss >> _method >> _url >> _http_version;

        _path = wwwroot;  // "wwwroot"

        if(_url == "/" || _url == "/index.html")
        {
            _path += "/";
            _path += homeage; // "wwwroot/index.html"
        }
        else
            _path += _url;
    }

    void Deserialize(std::string str)
    {
        // 请求行 /r/n
        // 报头 /r/n
        // 空行 /r/n
        // 内容
        
        while(1)
        {
            size_t pos = str.find("\r\n");
            if(pos == std::string::npos)
                break;
            
            std::string s = str.substr(0, pos);
            
            if(s.empty())
                break;
            
            _hander.push_back(s);
            str.erase(0, pos);
        }

        _text = str;
        prase();
    }
public:
    std::vector<std::string> _hander;
    std::string _text;
    std::string _path;
    std::string _method;
    std::string _url;
    std::string _http_version;
};

class HttpServer
{
public:
    HttpServer(uint16_t port)
        : _port(port)
    {}

    ~HttpServer()
    {}

    static std::string ReadHtmlContent(std::string path)
    {
        std::ifstream in(path);
        if(!in.is_open())
            return "404";
        
        std::string content;
        std::string line;
        while(getline(in, line))
        {
            content += line;
        }

        return content;
    }   
    static void* handler(void* argc)
    {
        pthread_detach(pthread_self());
        ThreadData* td = static_cast<ThreadData*>(argc);

        char inbuffer[4096];
        int sockfd = td->getsockfd();
        while(1)
        {
            HttpRequest rq;
            //浏览器断开后 recv就会返回0  然后应该离开循环 但是你下面还在send发送 导致出现了异常被操作系统杀掉
            int n = recv(sockfd, inbuffer, sizeof(inbuffer), 0); 
            if(n > 0)
            {
                inbuffer[n] = '\0';
                // std::cout << inbuffer;
                rq.Deserialize(inbuffer);
                rq.DebugPrint();
            }
            else
            {
                break;
            }

            // 响应
            // 状态行 Http_version 状态码 状态描述
            // 响应报头 \r\n
            // 空行 \r\n
            // content

            std::string filepath = rq._path;
            //std::string content = "I want to accompany you to the ends of the earth";
            std::string content = ReadHtmlContent(filepath);
            std::string response_line = "HTTP/1.0 200 OK\r\n";

            std::string response_hander = "Content-Length: ";
            response_hander += std::to_string(content.size());
            response_hander += "\r\n";

            response_hander += "\r\n";

            std::string response = response_line + response_hander + content;

            send(sockfd, response.c_str(), response.size(), 0);
        } 
        delete td;
    }

    bool start()
    {
        _listensock.Socket();
        _listensock.Bind(_port);
        _listensock.Listen();

        while(1)
        {
            std::string client_ip;
            uint16_t client_port;
            int sockfd = _listensock.Accept(client_ip, client_port);

            ThreadData* td = new ThreadData(sockfd);
            pthread_t pid;
            pthread_create(&pid, nullptr, handler, td);
        }

    }

private:
    Sock _listensock;
    uint16_t _port;
};

